home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1993, 1994 Marc Parmet.
- * This file is part of the Macintosh port of GNU Emacs.
- *
- * GNU Emacs is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
- #if defined(THINK_C)
- #include <MacHeaders>
- #else
- #include <Types.h>
- #include <Memory.h>
- #include <Quickdraw.h>
- #include <Windows.h>
- #include <TextEdit.h>
- #include <Errors.h>
- #include <LowMem.h>
- #include <Resources.h>
- #endif
-
- #include <Processes.h>
- #include "errno.h"
- #include "stdio.h"
- #include "sys/dir.h"
- #include "sys/ioctl.h"
- #include "unix-types.h"
- #include "unix-constants.h"
-
- #define PIPEBUFSIZE 1024
-
- struct unix_object **object_list;
-
- static char *
- getenv_internal(char *target)
- {
- char ***p,**e,*s,t[256],*strchr();
- int len;
-
- p = proctable[current_process_index].environ_address;
- if (p == 0L || *p == 0L) return 0L;
-
- for (e = *p; *e != 0L; ++e) {
- s = strchr(*e,'=');
- if (!s) continue;
- len = s - *e;
- if (len >= sizeof(t)) continue;
- memcpy(t,*e,len);
- t[len] = '\0';
- if (!strcmp(t,target)) return s+1;
- }
-
- return 0L;
- }
-
- void
- set_errno(int err)
- {
- struct proc *p = &proctable[current_process_index];
-
- if (p->errno_address == 0L) return;
-
- if (err > 0)
- *p->errno_address = err;
- else {
- switch (err) {
- case noErr: *p->errno_address = 0; break;
- case eofErr: *p->errno_address = EEOF; break;
- case dirNFErr:
- case nsvErr: *p->errno_address = ENOTDIR;break;
- case bdNamErr:
- case fnfErr: *p->errno_address = ENOENT; break;
- case permErr: *p->errno_address = EPERM; break;
- default: *p->errno_address = EUNDOC; break;
- }
- }
- }
-
- char *
- getwd_internal(char *u)
- {
- char *s = proctable[current_process_index].cwd_string;
- if (s == 0L || strlen(s) >= MAXPATHLEN)
- return 0L;
- else {
- strcpy(u,s);
- return u;
- }
- }
-
- struct unix_object **
- add_object(long flavor,long translate)
- {
- int err;
- struct unix_object **object;
-
- object = (struct unix_object **)NewHandle(sizeof(struct unix_object));
- err = MemError();
- if (err) return 0L;
-
- (**object).prev = 0L;
- (**object).next = object_list;
- if (object_list != 0L)
- (**object_list).prev = object;
- object_list = object;
- (**object).flavor = flavor;
- (**object).translate = translate;
- (**object).count = 1;
- return object;
- }
-
- static void
- remove_object(struct unix_object **object)
- {
- if (object_list == object)
- object_list = (**object).next;
- if ((**object).prev != 0L)
- (**(**object).prev).next = (**object).next;
- if ((**object).next != 0L)
- (**(**object).next).prev = (**object).prev;
- DisposHandle((Handle)object);
- }
-
- int
- dec_object_count(struct unix_object **object)
- {
- int count = --(**object).count;
- if (count == 0) remove_object(object);
- return count;
- }
-
- struct unix_object **
- lookup_object(long flavor,long data)
- {
- struct unix_object **object;
-
- for (object = object_list; object != 0L; object = (**object).next) {
- if ((**object).flavor == flavor) {
- switch (flavor) {
- case object_flavor_file:
- if (!bcmp((void *)data,&(**object).u.file.spec,sizeof(FSSpec)))
- return object;
- break;
- case object_flavor_pipe:
- if (data == (**object).u.pipe.pipeNum)
- return object;
- break;
- default:
- return object;
- }
- }
- }
-
- return 0L;
- }
-
- void
- add_given_fd(int index,int fd,long flavor,
- long (*dispatch)(long,long,long,char *,long,struct savearea_lomem *),
- struct unix_object **object)
- {
- struct proc *p = &proctable[index];
- p->fd[fd].flavor = flavor;
- p->fd[fd].object = object;
- p->fd[fd].dispatch = dispatch;
- }
-
- long
- add_fd(long flavor,long (*dispatch)(long,long,long,char *,long,struct savearea_lomem *),struct unix_object **object)
- {
- int i;
- for (i = 0; i<MAXDESC; ++i)
- if (proctable[current_process_index].fd[i].flavor == fd_flavor_unused) {
- add_given_fd(current_process_index,i,flavor,dispatch,object);
- return i;
- }
-
- return -1;
- }
-
- static int
- only_we_own_object(struct unix_object **object)
- {
- int i,j;
-
- for (i = 0; i<MAXPROC; ++i) {
- if (i == current_process_index) continue;
- if (proctable[i].pid == 0) continue;
- for (j = 0; j<MAXDESC; ++j)
- if (proctable[i].fd[j].flavor != fd_flavor_unused &&
- proctable[i].fd[j].object == object)
- return 0;
- }
-
- return 1;
- }
-
- static long
- pipe_dispatch(long task,long index,long fd,char *p,long n,struct savearea_lomem *lomem)
- {
- int i,taken,nleft,avail;
- int m,nwritten;
- struct unix_object **object;
-
- object = proctable[index].fd[fd].object;
-
- switch (task) {
- case unix_read:
- while (1) {
- taken = ((**object).u.pipe.wp + PIPEBUFSIZE - (**object).u.pipe.rp) & (PIPEBUFSIZE-1);
- avail = PIPEBUFSIZE-1 - taken;
- if (taken > 0) break;
- if (only_we_own_object(object))
- return 0; /* No one else can write, so EOF. */
- else {
- //printnum("$$$ Nothing to read, letting someone else write",index);
- run_another_process(); /* Let someone write */
- //printnum("$$$ Reading again",index);
- }
- }
-
- if (n > taken) n = taken;
- for (i = 0; i<n; ++i) {
- *p++ = (**object).u.pipe.pipeBuf[(**object).u.pipe.rp];
- (**object).u.pipe.rp = ((**object).u.pipe.rp + 1) & (PIPEBUFSIZE-1);
- }
- return n;
- case unix_write:
- nleft = n;
- nwritten = 0;
-
- while (1) {
- if (nleft == 0) return nwritten;
- /* This is not the right test, we need to keep a count of
- readers and writers. */
- if (only_we_own_object(object)) {
- raise_internal(SIGPIPE,lomem);
- return nwritten;
- }
- taken = ((**object).u.pipe.wp + PIPEBUFSIZE - (**object).u.pipe.rp) & (PIPEBUFSIZE-1);
- avail = PIPEBUFSIZE-1 - taken;
- if (avail == 0) {
- /* Let someone read */
- //printnum("### No room to write, letting someone else read",index);
- run_another_process();
- //printnum("### Writing again",index);
- continue;
- }
-
- m = nleft;
- if (m > avail) m = avail;
- for (i = 0; i<m; ++i) {
- (**object).u.pipe.pipeBuf[(**object).u.pipe.wp] = *p++;
- (**object).u.pipe.wp = ((**object).u.pipe.wp + 1) & (PIPEBUFSIZE-1);
- ++nwritten;
- --nleft;
- }
- }
- case unix_close:
- if ((**object).u.pipe.pipeBuf != 0L)
- DisposPtr((**object).u.pipe.pipeBuf);
- return 0;
- case unix_fionread:
- *(int *)p = ((**object).u.pipe.wp + PIPEBUFSIZE - (**object).u.pipe.rp) & (PIPEBUFSIZE-1);
- return 0;
- }
- }
-
- void
- kernel_entry(struct savearea_lomem *lomem)
- {
- if (lomem == 0L) return;
-
- GetPort(&lomem->port);
- lomem->zone = GetZone();
- lomem->curResFile = CurResFile();
- lomem->ApplLimit = LMGetApplLimit();
- lomem->HeapEnd = LMGetHeapEnd();
- lomem->HiHeapMark = LMHiHeapMark;
-
- SetZone(ApplicZone());
- }
-
- void
- kernel_exit(struct savearea_lomem *lomem)
- {
- if (lomem == 0L) return;
-
- SetZone(lomem->zone);
- UseResFile(lomem->curResFile);
- SetPort(lomem->port);
- LMSetApplLimit(lomem->ApplLimit);
- LMSetHeapEnd(lomem->HeapEnd);
- LMHiHeapMark = lomem->HiHeapMark;
- }
-
- static int unix_entry1(int,struct savearea_lomem *,va_list);
- static int ioctl_internal(int,int,int *,struct savearea_lomem *);
- static int isatty_internal(int);
-
- int
- unix_entry(int dispatch_code,int *errno_address,va_list arglist)
- {
- int i,result,in_front;
- int now = TickCount();
- struct proc *p = &proctable[current_process_index],*q;
- struct savearea_lomem lomem;
- extern char got_interrupt_from_terminal;
- extern int Vquit_in_main_event_loop;
-
- p->errno_address = errno_address;
-
- kernel_entry(&lomem);
-
- /* Pretend we have a multitasking operating system. */
- read_events(1);
- if (p->start_time + 60 <= now) run_another_process();
-
- /* Do the requested operation. */
- result = unix_entry1(dispatch_code,&lomem,arglist);
-
- /* Look for interrupts. */
- for (i = 0, q = proctable; i<MAXPROC; ++i, ++q) {
- if (q->pid != 0 && q->alarm_time != 0 && q->alarm_time <= now) {
- q->alarm_time = 0;
- kill_internal(q->pid,SIGALRM,&lomem);
- }
- }
- if (got_interrupt_from_terminal) {
- /* One day we'll do something reasonable with process groups. */
- got_interrupt_from_terminal = 0;
- kill_internal(proctable[0].pid,SIGINT,&lomem);
- }
- if (Vquit_in_main_event_loop) {
- Vquit_in_main_event_loop = 0;
- kill_internal(1,SIGKILL,&lomem);
- }
-
- kernel_exit(&lomem);
-
- return result;
- }
-
- static int
- unix_entry1(int dispatch_code,struct savearea_lomem *lomem,va_list arglist)
- {
- int err,fd,i,j,k,mode;
- char *s,*t;
- struct unix_object **object;
-
- switch (dispatch_code) {
- case unix_open:
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return open_internal(s,i);
- case unix_creat:
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return creat_internal(s,i);
- case unix_dup:
- i = va_arg(arglist,int);
- return dup_internal(i);
- case unix_dup2:
- i = va_arg(arglist,int);
- j = va_arg(arglist,int);
- if (proctable[current_process_index].fd[j].flavor != fd_flavor_unused) {
- err = close_internal(current_process_index,j,lomem);
- if (err == -1) return -1;
- }
-
- add_given_fd(current_process_index,j,
- proctable[current_process_index].fd[i].flavor,
- proctable[current_process_index].fd[i].dispatch,
- proctable[current_process_index].fd[i].object);
- ++(**proctable[current_process_index].fd[i].object).count;
- return j;
- case unix_read:
- case unix_write:
- i = va_arg(arglist,int);
- s = va_arg(arglist,char *);
- j = va_arg(arglist,int);
- return read_write_internal(dispatch_code,i,s,j,lomem);
- case unix_close:
- i = va_arg(arglist,int);
- return close_internal(current_process_index,i,lomem);
- case unix_lseek:
- i = va_arg(arglist,int);
- j = va_arg(arglist,int);
- k = va_arg(arglist,int);
-
- switch (k) {
- case 0: mode = fsFromStart; break;
- case 1: mode = fsFromMark; break;
- case 2: mode = fsFromLEOF; break;
- default: return -1;
- }
- err = SetFPos((**proctable[current_process_index].fd[i].object).u.file.refNum,mode,j);
- if (err) return -1;
- err = GetFPos((**proctable[current_process_index].fd[i].object).u.file.refNum,(long *)&j);
- if (err) return -1;
- return j;
- case unix_unlink:
- s = va_arg(arglist,char *);
- return unlink_internal(s);
- case unix_pipe:
- {
- int *fd = va_arg(arglist,int *);
- static int pipeNum = 0;
- void *t;
-
- /* fd[0] is for reading */
- /* fd[1] is for writing */
-
- fd[0] = add_fd(fd_flavor_pipe,pipe_dispatch,0L);
- if (fd[0] == -1) return -1;
- fd[1] = add_fd(fd_flavor_pipe,pipe_dispatch,0L);
- if (fd[1] == -1) { proctable[current_process_index].fd[fd[0]].flavor = fd_flavor_unused; return -1; }
-
- object = add_object(object_flavor_pipe,0);
- if (object == 0L) return -1;
- (**object).u.pipe.pipeNum = pipeNum++;
- t = NewPtr(PIPEBUFSIZE);
- (**object).u.pipe.pipeBuf = t;
- (**object).u.pipe.wp = (**object).u.pipe.rp = 0;
- if (MemError()) { dec_object_count(object); return -1; }
- ++(**object).count;
-
- proctable[current_process_index].fd[fd[0]].object = object;
- proctable[current_process_index].fd[fd[1]].object = object;
- return 0;
- }
- case unix_vfork1:
- return vfork1_internal();
- case unix_vfork2:
- i = va_arg(arglist,int);
- return vfork2_internal(lomem,i);
- case unix_execvp:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- return execvp_internal(s,(char **)t);
- case unix__exit:
- i = va_arg(arglist,int);
- _exit_internal(i);
- return -1; /* "Never happens" */
- case unix_exit:
- i = va_arg(arglist,int);
- exit_internal(i);
- return -1; /* "Never happens" */
- case unix_signal:
- i = va_arg(arglist,int);
- s = va_arg(arglist,char *);
- return signal_internal(i,(int (*)())s);
- case unix_raise:
- i = va_arg(arglist,int);
- return raise_internal(i,lomem);
- case unix_kill:
- i = va_arg(arglist,int);
- j = va_arg(arglist,int);
- return kill_internal(i,j,lomem);
- case unix_ioctl:
- i = va_arg(arglist,int);
- j = va_arg(arglist,int);
- s = va_arg(arglist,char *);
- return ioctl_internal(i,j,(int *)s,lomem);
- case unix_wait:
- s = va_arg(arglist,char *);
- return wait3_internal((long *)s,0,0);
- case unix_wait3:
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- j = va_arg(arglist,int);
- return wait3_internal((long *)s,i,j);
- case unix_alarm:
- i = va_arg(arglist,int);
- return alarm_internal(i);
- case unix_pause:
- return pause_internal();
- case unix_chdir:
- s = va_arg(arglist,char *);
- return chdir_internal(s);
- case unix_getwd:
- s = va_arg(arglist,char *);
- return (int)getwd_internal(s);
- case unix_sleep:
- i = va_arg(arglist,int);
- return sleep_internal(i);
- case unix_getpid:
- return proctable[current_process_index].pid;
- case unix_getppid:
- return proctable[current_process_index].ppid;
- case unix_unixfn2FSSpec:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return unixfn2FSSpec_internal(s,t,i);
- case unix_access:
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return access_internal(s,i);
- case unix_rename:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- return rename_internal(s,t);
- case unix_chmod:
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return chmod_internal(s,i);
- case unix_chgrp:
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return chgrp_internal(s,i);
- case unix_chown:
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return chown_internal(s,i);
- case unix_stat:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- return stat_internal(s,(struct stat *)t,0);
- case unix_lstat:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- return stat_internal(s,(struct stat *)t,1);
- case unix_stat_spec:
- s = va_arg(arglist,char *);
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return stat_spec_internal((FSSpec *)s,(struct stat *)t,i);
- case unix_isatty:
- i = va_arg(arglist,int);
- return isatty_internal(i);
- case unix_opendir:
- s = va_arg(arglist,char *);
- return opendir_internal(s);
- case unix_readdir:
- s = va_arg(arglist,char *);
- return readdir_internal((DIR *)s);
- case unix_closedir:
- s = va_arg(arglist,char *);
- return closedir_internal((DIR *)s);
- case unix_getenv:
- s = va_arg(arglist,char *);
- return (int)getenv_internal(s);
- case unix_readlink:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return readlink_internal(s,t,i);
- case unix_FSSpec2unixfn:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- return FSSpec2unixfn_internal((FSSpec *)s,(Handle *)t);
- case unix_symlink:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- return symlink_internal(s,t);
- case unix__iob:
- i = va_arg(arglist,int);
- return (int)&proctable[current_process_index].iob[i];
- case unix_fflush:
- s = va_arg(arglist,char *);
- return fflush_internal((FILE *)s,lomem);
- case unix_fclose:
- s = va_arg(arglist,char *);
- fclose_internal((FILE *)s,lomem);
- return 0;
- case unix_mkdir:
- s = va_arg(arglist,char *);
- i = va_arg(arglist,int);
- return mkdir_internal(s,i);
- case unix_rmdir:
- s = va_arg(arglist,char *);
- return rmdir_internal(s);
- case unix_utime:
- s = va_arg(arglist,char *);
- t = va_arg(arglist,char *);
- return utime_internal(s,(struct utimbuf *)t);
- case unix_unix_nop:
- return 0;
- }
- }
-
- void
- unix_translate(register char *p,register int n)
- {
- register char c;
-
- while (--n >= 0) {
- c = *p;
- if (c == '\015')
- *p = '\012';
- else if (c == '\012')
- *p = '\015';
- ++p;
- }
- }
-
- long
- close_internal(long index,long fd,struct savearea_lomem *lomem)
- {
- int result,count;
- struct unix_object **object;
-
- if (proctable[index].fd[fd].flavor == fd_flavor_unused) return 0;
- object = proctable[index].fd[fd].object;
- count = (**object).count;
- if (count == 1)
- result = (*proctable[index].fd[fd].dispatch)(unix_close,index,fd,0,0,lomem);
- else
- result = 0;
- dec_object_count(object);
- proctable[index].fd[fd].flavor = fd_flavor_unused;
- return result;
- }
-
- long
- close_all_internal(long index)
- {
- int i;
-
- for (i = 0; i<MAXDESC; ++i)
- close_internal(index,i,0L);
- return 0;
- }
-
- int
- chdir_internal(char *s)
- {
- Handle t;
- FSSpec spec;
- int err,len,at_root;
- struct proc *p = &proctable[current_process_index];
-
- err = unixfn2FSSpec_internal(s,&spec,0);
- if (err == nsDrvErr)
- at_root = 1;
- else {
- if (err) { set_errno(err); return -1; }
- at_root = 0;
- err = FSSpec2unixfn_internal(&spec,&t);
- if (err) { set_errno(err); return -1; }
- }
-
- if (p->cwd_string) {
- DisposPtr(p->cwd_string);
- p->cwd_string = 0L;
- }
- HLock(t);
- p->cwd_string = NewPtr((at_root ? 2 : strlen(*t)) + 1);
- err = MemError();
- HUnlock(t);
- if (err) { set_errno(err); return -1; }
- HLock(t);
- strcpy(p->cwd_string,at_root ? "/" : *t);
- HUnlock(t);
- if (!at_root) DisposHandle(t);
- return 0;
- }
-
- static int
- ioctl_internal(int fd,int job,int *data,struct savearea_lomem *lomem)
- {
- if (job != FIONREAD) { set_errno(EINVAL); return -1; }
- if (proctable[current_process_index].fd[fd].flavor == fd_flavor_unused) { set_errno(EINVAL); return -1; }
- return (*proctable[current_process_index].fd[fd].dispatch)
- (unix_fionread,current_process_index,fd,(char *)data,0,lomem);
- }
-
- static int
- isatty_internal(int fd)
- {
- return proctable[current_process_index].fd[fd].flavor == fd_flavor_dev_tty;
- }
-
- int
- dup_internal(int fd)
- {
- long new_fd;
- new_fd = add_fd(proctable[current_process_index].fd[fd].flavor,
- proctable[current_process_index].fd[fd].dispatch,
- proctable[current_process_index].fd[fd].object);
- if (new_fd == -1) return -1;
- ++(**proctable[current_process_index].fd[fd].object).count;
- return new_fd;
- }
-
- long
- read_write_internal(long dispatch_code,long fd,char *p,long n,struct savearea_lomem *lomem)
- {
- int result;
-
- if ((**proctable[current_process_index].fd[fd].object).translate && dispatch_code == unix_write)
- unix_translate(p,n);
-
- result = (*proctable[current_process_index].fd[fd].dispatch)
- (dispatch_code,current_process_index,fd,p,n,lomem);
-
- if ((**proctable[current_process_index].fd[fd].object).translate)
- unix_translate(p,result);
-
- return result;
- }
-